home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-20 / pmpsrc11.zip / LEVEL1TX.C < prev    next >
Text File  |  1991-07-30  |  6KB  |  257 lines

  1. /*
  2.     level1.c -- Level 1 synchronous transmission routines
  3.  
  4.   Poor Man's Packet (PMP)
  5.   Copyright (c) 1991 by Andrew C. Payne    All Rights Reserved.
  6.  
  7.   Permission to use, copy, modify, and distribute this software and its
  8.   documentation without fee for NON-COMMERCIAL AMATEUR RADIO USE ONLY is hereby
  9.   granted, provided that the above copyright notice appear in all copies.
  10.   The author makes no representations about the suitability of this software
  11.   for any purpose.  It is provided "as is" without express or implied warranty.
  12.  
  13.     07/24/89
  14.      Andrew C. Payne
  15. */
  16.  
  17. /* ----- Includes ----- */
  18. #include <stdio.h>
  19. #include <alloc.h>
  20. #include <dos.h>
  21. #include "pmp.h"
  22. #include "ports.h"
  23. #include "crc.h"
  24.  
  25. /* ----- External Assembly Routines ----- */
  26. extern word timer(void);
  27. extern word transit(word when);
  28.  
  29. #define MAXTXQUEUE      50    /* max size of TXQueue */
  30.  
  31. /* ----- Local Variables ----- */
  32.  
  33. static struct ax25_level1 *TXQueue[MAXTXQUEUE];    /* Transmit queue */
  34. static int    TXQSize;            /* number of items in queue */
  35.        int    TXQBytes;            /* total bytes in queue */
  36.  
  37. static int    bitsent;            /* # of bits sent */
  38.  
  39. /* ----- CRC Generation and Checking ----- */
  40. /* CRCCheck(packet)
  41.     Given a packet, generates a CRC, checks with existing CRC, and sets
  42.     valid CRC.
  43. */
  44. int CRCCheck(struct ax25_level1 *packet)
  45. {
  46.     word    crc;
  47.     int    len;        /* packet length, data bytes */
  48.     int    i;
  49.     byte    *p,t;
  50.     word    q;
  51.  
  52.     p = packet->data;    /* pointer to data */
  53.     len = packet->len-2;    /* length less CRC bytes */
  54.  
  55. /* compute CRC */
  56.     crc = 0xffff;        /* initialize */
  57.     for(i=0; i<len; i++) {
  58.         t = *p++ ^ (crc & 0xff);
  59.         crc >>= 8;
  60.         crc ^= crc_table[t];
  61.     }
  62.     q = ~crc;
  63.  
  64.     crc = *((word *)p);    /* fetch existing */
  65.     *((word *)p) = q;    /* store computed one */
  66.  
  67.     return crc == q;    /* return OK or not OK */
  68. }
  69.  
  70. /* ----- Clock Skewing ----- */
  71. /* ClockAdjust(bitcount)
  72.     Speeds up the BIOS clock depending on the number of bits specified.
  73. */
  74. void ClockAdjust(int bitcount)
  75. {
  76.     if(ClockSkew) {
  77.         bitcount = (bitcount / BITSPERTICK) - 1;
  78.         while(bitcount-- > 0)
  79.             geninterrupt(8);    /* BIOS timer */
  80.     }
  81. }
  82.  
  83. /* ----- Transmission Subroutines ----- */
  84.  
  85. /* sendflags(from,count)
  86.     Sends 'count' opening flags, synced with the transition at time
  87.     'from'.  Returns time of last transition.
  88. */
  89. static word sendflags(register word from, int count)
  90. {
  91.     while(count--) {
  92.         transit(from -= BITTIME);
  93.         transit(from -= BITTIME*7);
  94.     }
  95.     bitsent += 8;
  96.     return from;            /* time of last transition */
  97. }
  98.  
  99. /* sendpacketdata(from,p)
  100.     Given a data packet, sends data packet synced with the transition
  101.     at time 'from'.  Returns the time of the last transition.
  102.  
  103.     NOTE:  the 'c' variable MUST be an integer size.
  104. */
  105. static word sendpacketdata(word from, struct ax25_level1 *packet)
  106. {
  107.     int    len;            /* bytes left to send */
  108.     byte    *p;            /* pointer to data */
  109.     word    c;            /* current character to transmit */
  110.     int    bit;            /* bits left in c */
  111.     int    count;            /* count of one bits */
  112.  
  113.  
  114. /* initialize pointers and counters */
  115.     len = packet->len;
  116.     p = packet->data;
  117.  
  118. /* send the packet */
  119.     bit = 0;
  120.     while(TRUE) {
  121.         count = 0;
  122.  
  123. /* find next zero bit, or five consecutive ones */
  124.         do {
  125.             if(!bit) {        /* end of byte? */
  126.                 if(len-- == 0) {
  127.                     if(count == 5) {
  128.                         transit(from  -= BITTIME * 6);
  129.                         bitsent += 6;
  130.                         return from;
  131.                     } else
  132.                         return from - count * BITTIME;
  133.                 }
  134.  
  135.                 c = *p++;    /* get next byte */
  136.                 bit = 7;
  137.             } else {        /* else, next in next bit */
  138.                 c >>= 1;
  139.                 bit--;
  140.             }
  141.             count++;
  142.         } while(count < 6 && (c & 1));
  143.  
  144. /* if stuffed zero, undo last bit */
  145.         if(count == 6) {
  146.             bit++;
  147.             c <<= 1;
  148.         }
  149.  
  150. /* make next transition */
  151.         transit(from -= count * BITTIME);
  152.         bitsent += count;
  153.     }
  154. }
  155.  
  156. /* ----- Transmitter Control ----- */
  157.  
  158. /* TXKey(state)
  159.     Sets the transmitter state to the state given (TRUE = 1 = keyup).
  160.     Updates the status line on the screen.
  161. */
  162. void TXKey(int state)
  163. {
  164.     if((state != 0) != (PTTLevel != 0))
  165.         outportb(PTTPort,inportb(PTTPort) | PTTBit);
  166.     else
  167.         outportb(PTTPort,inportb(PTTPort) & ~PTTBit);
  168.  
  169.     ShowTXRX(state,FALSE);
  170. }
  171.  
  172.  
  173. /* ----- Transmit Queue Manipulation ----- */
  174.  
  175. /* TXQInit()
  176.     Initializes the level 1 transmit queue.
  177. */
  178. void TXQInit()
  179. {
  180.     TXQBytes = TXQSize = 0;        /* empty queue */
  181. }
  182.  
  183. /* TXQAdd(packet)
  184.     Adds a packet to the TXQueue.  Returns TRUE if successful, or
  185.     FALSE if error.
  186.  
  187.     Computes and sets CRC for packet.
  188.  
  189.     'packet' is a pointer to an AX.25 level 1 packet record, that was
  190.     alloced with the malloc() function.
  191. */
  192. int TXQAdd(struct ax25_level1 *packet)
  193. {
  194. /* check for full queue */
  195.     if(TXQSize >= MAXTXQUEUE)
  196.         return FALSE;
  197.  
  198. /* compute and set CRC */
  199.     (void) CRCCheck(packet);
  200.  
  201. /* add to TXQueue */
  202.     TXQBytes += packet->len;
  203.     TXQueue[TXQSize++] = packet;
  204.     return TRUE;
  205. }
  206.  
  207. /* TXQEmpty()
  208.     Assumes a clear channel, keys transmitter and empties TX queue.
  209.  
  210.     Frees all TX queue entries.
  211. */
  212. void TXQEmpty()
  213. {
  214.     word    from;
  215.     int    i;
  216.  
  217. /* is there anything in the queue to send? */
  218.     if(TXQSize) {
  219.  
  220.         TXKey(TRUE);        /* key up transmitter */
  221.         from = timer();        /* get current time */
  222.         bitsent = 0;        /* clear bit sent count */
  223.         disable();        /* kill interrupts */
  224.  
  225. /* send all packets in the TX Queue */
  226.         from = sendflags(from,TXStartFlags);    /* send flags */
  227.         for(i=0; i<TXQSize; i++) {
  228.             from = sendpacketdata(from,TXQueue[i]);
  229.             from = sendflags(from,TXEndFlags);
  230.         }
  231.         TXKey(FALSE);        /* drop transmitter key */
  232.         enable();        /* interrupts allowed */
  233.  
  234. /* attempt to re-adjust the BIOS clock */
  235.         ClockAdjust(bitsent);
  236.  
  237. /* free all packets in the TX Queue */
  238.         for(i=0; i<TXQSize; i++) {
  239. #ifdef TRACE
  240.             if(DebugMode)
  241.                 LogPacket(TXQueue[i],2); /* log the packet */
  242. #endif
  243.             free(TXQueue[i]);
  244.         }
  245.         TXCount += TXQSize;
  246.         TXQBytes = TXQSize = 0;
  247.     }
  248. }
  249.  
  250. /* TXQBytesInQ()
  251.     Returns the number of bytes currently in the Level 1 TX queue.
  252. */
  253. int TXQBytesInQ(void)
  254. {
  255.     return TXQBytes;
  256. }
  257.